import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;

public class Client {
	/**
	 * @param args
	 *            args[1] hostname args[2] port number
	 */
	public static void main(String[] args) {
		int nargs = args.length;
		int port = 80;
		String host = "localhost";
		Client client;
		System.out.println("Client launch");

		if (nargs < 2) {
			System.out.println("Use the default value IPdest: " + host
					+ " port : " + port);
		} else {
			host = args[0];
			port = Integer.parseInt(args[1]);
			System.out.println("Use destination value IPdest: " + host
					+ " port : " + port);
		}

		// create a client and open the socket
		client = new Client(host, port);
		ClientUi clientUi = new ClientUi(client);
		client.setClientUi(clientUi);
		client.connect();
		System.out.println("+++++++++++++++++++++++++++ \n\n");
	}

	private String host;
	private int port;
	private Socket socket;
	private InputStream in;
	private OutputStream out;
	private ObjectInputStream objIn = null;
	private ObjectOutputStream objOut;
	private ClientUi clientUi;

	public Client(String host, int port) {
		this.host = host;
		this.port = port;
	}
	/**
	 * Function to connect the client to the hangman server
	 * 
	 */
	public void connect() {
		try {
			System.out.println("Host" + host + "Port" + port);
			socket = new Socket(host, port);
			socket.setSoTimeout(10000);

			this.in = socket.getInputStream();

			this.out = socket.getOutputStream();
			this.objOut = new ObjectOutputStream(this.out);

		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (ConnectException e) {
			System.out.println("Connection refused");
			clientUi.labError.setText("Connection to the server failed");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Function to send a message to the client attribute to the socketClient
	 * 
	 * @param msg : content the Message to send to the client
	 */
	public void sendMsg(Message msg) {
		try {
			if (this.objOut != null) {
				this.objOut.writeObject(msg);
				this.objOut.flush();
				System.out.print("\n Message send : " +msg +"\n\n");
			}
		} catch (SocketException e) {
			System.out.println("Failed to send message to the server due to :"
					+ e.getCause());
			clientUi.labError
					.setText("Failed to send message to the server due to :"
							+ e.getCause());
		} catch (EOFException e) {
			System.out
					.println("Problem occur while communating with the server");
			clientUi.labError
					.setText("Problem occur while communating with the server");
		} catch (IOException e) {
			System.out
					.println("Problem occur while communating with the server");
			clientUi.labError
					.setText("Problem occur while communating with the server");
		}
	}
	/**
	 * Function to read a message from the server
	 * @return message received from the server
	 */
	public Message readMsg() {
		Message msg = null;
		try {
			if (this.objIn == null && this.in != null) {
				this.objIn = new ObjectInputStream(this.in);
			}
			if (this.in != null) {
				msg = (Message) this.objIn.readObject();
				System.out.print("\n Message read : " +msg +"\n\n");
				
			}
		} catch (EOFException e) {
			System.out
					.println("Problem occur while receiving the answer, connection may be broke");
			clientUi.labError
					.setText("Problem occur while receiving the answer, connection may be broke");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return msg;
	}

	/**
	 * Function to call when the Client should be close
	 */
	public void close() {
		try {
			if (objIn != null) {
				objIn.close();
			}
			if (objOut != null) {
				objOut.close();
			}
			if (objOut != null) {
				socket.close();
			}
		} catch (SocketException e) {
			System.out.println("Connection already closed");
			clientUi.labError.setText("Connection already closed");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public ClientUi getClientUi() {
		return clientUi;
	}

	public void setClientUi(ClientUi clientUi) {
		this.clientUi = clientUi;
	}
}
